package com.kelvin.paopao.api;

import android.support.annotation.NonNull;

import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import com.kelvin.kelvinlib.utils.LogUtil;
import com.kelvin.paopao.PaoPaoApplication;
import com.kelvin.paopao.api.responseBean.CheckTalkModel;
import com.kelvin.paopao.api.responseBean.CommonListResponse;
import com.kelvin.paopao.api.responseBean.DateListModel;
import com.kelvin.paopao.api.responseBean.DatePersonModel;
import com.kelvin.paopao.api.responseBean.GoodDetailModel;
import com.kelvin.paopao.api.responseBean.KefuModel;
import com.kelvin.paopao.api.responseBean.LocationPickModel;
import com.kelvin.paopao.api.responseBean.NearByPersonModel;
import com.kelvin.paopao.api.responseBean.OrderModel;
import com.kelvin.paopao.api.responseBean.PeisongModel;
import com.kelvin.paopao.api.responseBean.PersonPhotoModel;
import com.kelvin.paopao.api.responseBean.TagModel;
import com.kelvin.paopao.api.responseBean.TalkPriceModel;
import com.kelvin.paopao.api.responseBean.UserDetailModel;
import com.kelvin.paopao.api.responseBean.UserGz;
import com.kelvin.paopao.api.responseBean.UserMoneyBean;
import com.kelvin.paopao.api.responseBean.VipPriceModel;
import com.kelvin.paopao.api.responseBean.WalletDetailModel;
import com.kelvin.paopao.utils.Constant;
import com.kelvin.paopao.utils.NetUtil;
import com.hyphenate.easeui.utils.SpUtil;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by kelvin on 2017/05/05.
 * 整个网络通信服务的启动控制，必须先调用初始化函数才能正常使用网络通信接口
 */
public class RetrofitService {


    //设缓存有效期为1天
    static final long CACHE_STALE_SEC = 60 * 60 * 24 * 1;
    //查询缓存的Cache-Control设置，为if-only-cache时只查询缓存而不会请求服务器，max-stale可以配合设置缓存失效时间
    private static final String CACHE_CONTROL_CACHE = "only-if-cached, max-stale=" + CACHE_STALE_SEC;
    //查询网络的Cache-Control设置
    //(假如请求了服务器并在a时刻返回响应结果，则在max-age规定的秒数内，浏览器将不会发送对应的请求到服务器，数据由缓存直接返回)
    static final String CACHE_CONTROL_NETWORK = "Cache-Control: public, max-age=3600";
    // 避免出现 HTTP 403 Forbidden，参考：http://stackoverflow.com/questions/13670692/403-forbidden-with-java-but-not-web-browser
    static final String AVOID_HTTP403_FORBIDDEN = "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11";


    // 递增页码
    private static final int INCREASE_PAGE = 20;

    private static IUsersApi mUserApi;
    private static IOrderApi mOrderApi;

    private RetrofitService() {
        throw new AssertionError();
    }

    /**
     * 初始化网络通信服务
     */
    public static void init() {
        // 指定缓存路径,缓存大小100Mb
        Cache cache = new Cache(new File(PaoPaoApplication.getContext().getCacheDir(), "HttpCache"),
                1024 * 1024 * 100);
        OkHttpClient okHttpClient = new OkHttpClient.Builder().cache(cache)
                .retryOnConnectionFailure(true)
                .addInterceptor(getHttpLogInterceptor())
                .addInterceptor(sRewriteCacheControlInterceptor)
                .addNetworkInterceptor(sRewriteCacheControlInterceptor)
                .connectTimeout(30, TimeUnit.SECONDS)
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(Constant.USER_URL)
                .build();
        mUserApi = retrofit.create(IUsersApi.class);


        mOrderApi = retrofit.create(IOrderApi.class);
    }

    public static HttpLoggingInterceptor getHttpLogInterceptor() {
        return new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
    }

    /**
     * 云端响应头拦截器，用来配置缓存策略
     * Dangerous interceptor that rewrites the server's cache-control header.
     */
    private static final Interceptor sRewriteCacheControlInterceptor = new Interceptor() {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            if (!NetUtil.isNetworkAvailable(PaoPaoApplication.getContext())) {
                request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();
                LogUtil.d("no network");
            }
            Response originalResponse = chain.proceed(request);

            if (NetUtil.isNetworkAvailable(PaoPaoApplication.getContext())) {
                //有网的时候读接口上的@Headers里的配置，你可以在这里进行统一的设置
                String cacheControl = request.cacheControl().toString();
                return originalResponse.newBuilder()
                        .header("Cache-Control", cacheControl)
                        .removeHeader("Pragma")
                        .build();
            } else {
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, " + CACHE_CONTROL_CACHE)
                        .removeHeader("Pragma")
                        .build();
            }
        }
    };


    @NonNull
    private static String parseParams(RequestBody body, Buffer requestBuffer) throws UnsupportedEncodingException {
        if (body.contentType() != null && !body.contentType().toString().contains("multipart")) {
            return URLDecoder.decode(requestBuffer.readUtf8(), "UTF-8");
        }
        return "null";
    }

    /************************************ 用户类API *******************************************/

    /**
     * 获取附近的人
     *
     * @return
     */
    public static Observable<CommonListResponse<NearByPersonModel>> getNearPerson(String lng, String lat, String page_index,
                                                                                  String user_sex
            , String user_shengao, String user_tizhong, String user_Label, String user_type) {
        return mUserApi.getNearPerson(lng, lat, "user_near", page_index, user_sex, user_shengao, user_tizhong, user_Label, user_type).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 更新当前地理位置
     *
     * @return
     */
    public static Observable<CommonListResponse> updateLocation(String lng, String lat) {
        return mUserApi.updateLocation(lng, lat, "user_online_edit",
                SpUtil.getLoginphone(PaoPaoApplication.getContext()))
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 註冊
     *
     * @return
     */
    public static Observable<CommonListResponse> register(String user_sex, String user_id,
                                                          String user_name,
                                                          String user_pwd, String user_tel,
                                                          String user_headimg, String user_province,
                                                          String user_city, String user_age, String code) {
        return mUserApi.register(user_sex, user_id, user_name, "user_zhuce_v2", user_pwd, user_tel, user_headimg
                , user_province, user_city, user_age, code)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 登录
     *
     * @return
     */
    public static Observable<CommonListResponse<UserDetailModel>> login(String user_id, String user_pwd, String weixin_id) {
        return mUserApi.login("user_login", user_pwd, user_id, weixin_id)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 获取用户详情
     *
     * @param user_no
     * @return
     */
    public static Observable<CommonListResponse<UserDetailModel>> getUserInfo(String user_no) {
        return mUserApi.getUserDetail("user_info", user_no)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 关注用户
     *
     * @param user_no
     * @return
     */
    public static Observable<CommonListResponse> focus(String user_no) {
        return mUserApi.focus("user_gz", user_no, SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()),
                "1")
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 取消关注用户
     *
     * @param user_no
     * @return
     */
    public static Observable<CommonListResponse> unfocus(String user_no) {
        return mUserApi.unfocus("user_gz", user_no, SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()),
                "0")
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 是否关注用户
     *
     * @param user_no
     * @return
     */
    public static Observable<CommonListResponse<UserGz>> checkFocus(String user_no) {
        return mUserApi.checkFocus("check_user_gz", user_no,
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext())
        )
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 上传个人相册
     *
     * @param user_img
     * @return
     */
    public static Observable<CommonListResponse> addPersonPhoto(String user_img) {
        return mUserApi.addPersonPhoto("user_img_add", user_img,
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()));

    }

    /**
     * 获取个人相册
     *
     * @return
     */
    public static Observable<CommonListResponse<PersonPhotoModel>> getPersonPhoto() {
        return mUserApi.getPersonPhoto("user_img_list",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()));

    }

    /**
     * 获取个人相册
     *
     * @return
     */
    public static Observable<CommonListResponse<PersonPhotoModel>> getPersonPhoto(String user_no) {
        return mUserApi.getPersonPhoto("user_img_list",
                user_no).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());

    }

    /**
     * 删除个人相册
     *
     * @return
     */
    public static Observable<CommonListResponse> removePersonPhoto(String photo_id) {
        return mUserApi.removePersonPhoto("user_img_delete", photo_id,
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()));

    }

    /**
     * 获取好友
     *
     * @return
     */
    public static Observable<CommonListResponse<DatePersonModel>> getFriend() {
        return mUserApi.getFriend("user_gz_list",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()))
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());


    }

    /**
     * 编辑个人详情
     *
     * @return
     */
    public static Observable<CommonListResponse> updateInfo(String user_name, String user_age, String user_qianming, String user_zhiye,
                                                            String user_tizhong, String user_shengao, String user_province, String user_city
            , String user_ganqing, String user_label) {
        return mUserApi.updateInfo("user_info_edit", user_name, user_age, user_qianming,
                user_zhiye, user_tizhong, user_shengao, user_province, user_city,
                SpUtil.getLoginphone(PaoPaoApplication.getContext()), user_ganqing, user_label)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());

    }


    /**
     * 获取送货地址列表
     *
     * @return
     */
    public static Observable<CommonListResponse<LocationPickModel>> getLocationPick() {
        return mUserApi.getLocationPick("user_address_list",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()))
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());


    }

    /**
     * 获取剩余聊天时间
     *
     * @return
     */
    public static Observable<CommonListResponse<CheckTalkModel>> talkCheck(String toUserno) {
        return mUserApi.checkTalk("talk_check",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()), toUserno)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取聊天费用
     *
     * @return
     */
    public static Observable<CommonListResponse<TalkPriceModel>> getTalkMoney(String user_no) {
        return mUserApi.getTalkMoney("user_talkinfo",
                user_no)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 添加送货地址
     *
     * @return
     */
    public static Observable<CommonListResponse> addLocationPick(String address, String tel, String username,
                                                                 String lname, String lat, String lng) {
        return mUserApi.addLocationPick("user_address",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()),
                address, tel, username, "0", lname, lat, lng)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 支付聊天时间
     *
     * @return
     */
    public static Observable<CommonListResponse> payTalk(String user_no, String hours) {
        return mUserApi.payTalk("talk_order",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()),
                user_no, hours)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 设置配送价格
     *
     * @return
     */
    public static Observable<CommonListResponse> setPsPrice(String price) {
        return mUserApi.setPsPrice("user_psprice_set",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()), price)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 设置聊天费用
     *
     * @return
     */
    public static Observable<CommonListResponse> setTalkMoney(String price) {
        return mUserApi.setTalkMoney("user_talkset",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()), price)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 设置聊天费用
     *
     * @return
     */
    public static Observable<CommonListResponse> resetPwd(String pwd, String code, String mobile) {
        return mUserApi.resetPwd("user_setpwd",
                mobile, code, pwd)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 获取验证码
     *
     * @param phone
     * @return
     */
    public static Observable<CommonListResponse> getValidation(String phone, String types) {
        return mUserApi.getValidation("user_smscode", phone, types)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取标签
     *
     * @return
     */
    public static Observable<CommonListResponse<TagModel>> getLabelInfo() {
        return mUserApi.getLabelInfo("Label_info")
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取标签
     *
     * @return
     */
    public static Observable<CommonListResponse<KefuModel>> getKefu() {
        return mUserApi.getKefu("kefu_info")
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 判断手机是否注册
     *
     * @return
     */
    public static Observable<CommonListResponse> checkPhone(String phone) {
        return mUserApi.checkPhone("check_mobile_zc", phone)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /************************************邀约类API*******************************************/

    /**
     * 发布邀约
     *
     * @return
     */
    public static Observable<CommonListResponse> publishDate(String type, String item_title,
                                                             String oAddress, String oSex,
                                                             String oPayMode, String Istip,
                                                             String tipPrice, String hours,
                                                             String IsJie, String IsFriend,
                                                             String Remark, String ordertype,
                                                             String userno, String Img1,
                                                             String Img2, String Img3, String oAddressId, String oDate) {
        return mOrderApi.publishDate("order_add", item_title, oAddress, oSex, oPayMode, Istip, tipPrice, hours
                , IsJie, IsFriend, Remark, ordertype, userno, Img1, Img2, Img3, oAddressId, oDate).subscribeOn(Schedulers.io()).
                observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取邀约列表
     *
     * @param order_type
     * @return
     */
    public static Observable<CommonListResponse<DateListModel>> getDate(String order_type) {
        return mOrderApi.getDate("order_list", order_type, "").subscribeOn(Schedulers.io()).
                observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取我的邀约列表
     *
     * @return
     */
    public static Observable<CommonListResponse<DateListModel>> getMyDate() {
        return mOrderApi.getDate("order_list", "", SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()))
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 报名邀约
     *
     * @return
     */
    public static Observable<CommonListResponse> signup(String id) {
        return mOrderApi.signup("order_baoming", SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()), id)
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 获取报名人
     *
     * @return
     */
    public static Observable<CommonListResponse<DatePersonModel>> getDatePerson(String id) {
        return mOrderApi.getDatePerson("order_baoming_list", id)
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取报名人
     *
     * @return
     */
    public static Observable<CommonListResponse> confirm(String id, String user_no) {
        return mOrderApi.confirm("order_baoming_sure", id, user_no)
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 报名取消
     *
     * @return
     */
    public static Observable<CommonListResponse> dateCancel(String id, String user_no) {
        return mOrderApi.dateCancel("order_baoming_cal", id, user_no)
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 我的报名
     *
     * @return
     */
    public static Observable<CommonListResponse<DateListModel>> getMyAskDate(String oId) {
        return mOrderApi.getMyAskDate("order_baoming_self",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()), oId)
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 获取账号余额
     *
     * @return
     */
    public static Observable<CommonListResponse<UserMoneyBean>> getMoney() {
        return mUserApi.getMoney("user_blance",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()))
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取vip价格
     *
     * @return
     */
    public static Observable<CommonListResponse<VipPriceModel>> getVipPrice() {
        return mUserApi.getVipPrice("vip_list",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()))
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取vip价格
     *
     * @return
     */
    public static Observable<CommonListResponse> becomeVIP(String id) {
        return mUserApi.becomeVIP("user_vip",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()), id)
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取账号余额
     *
     * @return
     */
    public static Observable<CommonListResponse> recharge(String money) {
        return mUserApi.recharge("user_chongzhi",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()), money)
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取资金明细
     *
     * @return
     */
    public static Observable<CommonListResponse<WalletDetailModel>> getAccount(String account_type) {
        return mUserApi.getAccount("user_account", account_type,
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()))
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取商品详情
     *
     * @return
     */
    public static Observable<CommonListResponse<GoodDetailModel>> getGoodDetail(String sid) {
        return mOrderApi.getGoodDetail("shop_item_info", sid)
                .subscribeOn(Schedulers.io()).
                        observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 下单
     *
     * @return
     */
    public static Observable<CommonListResponse> takeorder(String sId, String aId,
                                                           String oNum, String oPayMode, String oRemarks) {
        return mOrderApi.takeorder("order_shop", sId, SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()),
                aId, oNum, oPayMode, " ")
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 获取我的订单
     *
     * @return
     */
    public static Observable<CommonListResponse<OrderModel>> getOrder() {
        return mOrderApi.getOrder("shop_order_list",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()))
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取配送列表
     *
     * @return
     */
    public static Observable<CommonListResponse<PeisongModel>> getPeisonList(String pageIndex) {
        return mOrderApi.getPeisonList("order_near", String.valueOf(Constant.latitude), String.valueOf(Constant.longtitude)
                , pageIndex)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 报名配送
     *
     * @return
     */
    public static Observable<CommonListResponse> requestPeisong(String oId) {
        return mOrderApi.requestPeisong("peisong_baoming", SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()),
                oId)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取配送报名名单
     *
     * @return
     */
    public static Observable<CommonListResponse<UserDetailModel>> getPeisongPerson(String oId) {
        return mOrderApi.getPeisongPerson("peisong_baoming_list", oId)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 获取配送确认
     *
     * @return
     */
    public static Observable<CommonListResponse> peisongConfirm(String user_no, String oid) {
        return mOrderApi.peisongConfirm("peisong_baoming_sure", user_no, oid)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }


    /**
     * 获取配送确认
     *
     * @return
     */
    public static Observable<CommonListResponse<PeisongModel>> getMyRequestPeisong(String oId) {
        return mOrderApi.getMyRequestPeisong("peisong_baoming_self",
                SpUtil.getLoginHuanxin_id(PaoPaoApplication.getContext()), oId)
                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

}
